home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / FDF101.ARJ / FDFCOMM.C < prev    next >
C/C++ Source or Header  |  1992-04-29  |  12KB  |  546 lines

  1. /*
  2.  * fdfcomm.c
  3.  *
  4.  * common functions for find duplicates program
  5.  *
  6.  * Roy Bixler
  7.  * March 23, 1991
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 1, or (at your option)
  12.  * any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22.  */
  23.  
  24.  
  25.  
  26. #include <ctype.h>
  27. #include <dir.h>
  28. #include <dos.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include <stdio.h>
  32. #include <sys\types.h>    /* must be included before stat.h */
  33. #include <sys\stat.h>
  34.  
  35. #include "cmp.h"
  36. #include "fdfcomm.h"
  37. #include "elib.h"
  38.  
  39.  
  40.  
  41. FILE_LIST *F_list = NULL, *I_del_menu[N_INTERACTIVE];
  42. char Match_criteria = 0, Sort_criteria = 0, Sort_order = ASCENDING;
  43. char i_flag = 0;    /* interactive delete mode */
  44. char l_flag = 0;    /* long listing? */
  45. char v_flag = 0;    /* verbose? */
  46. static char Sorted;
  47.  
  48.  
  49.  
  50. /*
  51.  * print_fdate
  52.  *
  53.  * given a dta structure, print out the date in it
  54.  */
  55. void print_fdate(struct ffblk *dta)
  56.  
  57. {
  58.     printf("%02d/%02d/%02d",
  59.            (dta->ff_fdate >> 9) + 80,
  60.            (dta->ff_fdate >> 5) & 0xf,
  61.            (dta->ff_fdate) & 0x1f);
  62. }
  63.  
  64.  
  65.  
  66. /*
  67.  * print_ftime
  68.  *
  69.  * given a dta structure, print out the time in it
  70.  */
  71. void print_ftime(struct ffblk *dta)
  72.  
  73. {
  74.     printf("%02d:%02d:%02d",
  75.            (dta->ff_ftime >> 11),
  76.            (dta->ff_ftime >> 5) & 0x3f,
  77.            (dta->ff_ftime & 0x1f));
  78. }
  79.  
  80.  
  81.  
  82. /*
  83.  * print_fdatetime
  84.  *
  85.  * print the given dta's date, a space and the dta's time
  86.  */
  87. void print_fdatetime(struct ffblk *dta)
  88.  
  89. {
  90.     print_fdate(dta);
  91.     printf(" ");
  92.     print_ftime(dta);
  93. }
  94.  
  95.  
  96.  
  97. /*
  98.  * print_fpath
  99.  *
  100.  * given a path and a dta, print the path with the dta's name tacked on the
  101.  * end
  102.  */
  103. void print_fpath(char *path, char *f_name)
  104.  
  105. {
  106.     static char *dir_sep = PATH_SEPARATOR;
  107.     int path_len;
  108.  
  109.     if (path != NULL) {
  110.         path_len = strlen(path);
  111.         printf("%s%s%s", path,
  112.                ((path_len > 0) && (path[path_len-1] == dir_sep[0]))
  113.                 ? ""
  114.                 : PATH_SEPARATOR,
  115.                 f_name);
  116.     }
  117. }
  118.  
  119. /*
  120.  * long_listing
  121.  *
  122.  * print out the complete information on the given file
  123.  */
  124. void long_listing(char *path, struct ffblk *dta)
  125.  
  126. {
  127.     if (path != NULL) {
  128.         printf("%c ", (dta->ff_attrib == 0x10) ? 'd' : '-');
  129.         print_fdatetime(dta);
  130.         printf(" %8ld ", dta->ff_fsize);
  131.          print_fpath(path, dta->ff_name);
  132.         printf("\n");
  133.     }
  134. }
  135.  
  136. /*
  137.  * print_match_header
  138.  *
  139.  * prints the first match of files
  140.  */
  141. void print_match_header(FILE_LIST *start)
  142.  
  143. {
  144.     if (l_flag)
  145.         return;    /* no header */
  146.     else if (Match_criteria & NAMES_MATCH)
  147.         printf("file %s found in directories:\n", start->dta.ff_name);
  148.     else if (Match_criteria & CONTENTS_MATCH)
  149.         printf("files with matching contents (size = %ld) found:\n",
  150.                start->dta.ff_fsize);
  151.     else if (Match_criteria & SIZES_MATCH)
  152.         printf("files of length %ld found:\n", start->dta.ff_fsize);
  153.     else if (Match_criteria & TIMES_MATCH) {
  154.         printf("files with timestamp ");
  155.         print_fdatetime(&start->dta);
  156.         printf(" found:\n");
  157.     }
  158. }
  159.  
  160.  
  161.  
  162. /*
  163.  * print_next_match
  164.  *
  165.  * prints out any matches after the first one
  166.  */
  167. void print_next_match(FILE_LIST *next, int menu_num)
  168.  
  169. {
  170.     if (menu_num >= 0)
  171.         printf("%d)%s", menu_num, (l_flag) ? " " : "");
  172.     if (l_flag)
  173.         long_listing(next->path, &next->dta);
  174.     else if (Match_criteria & NAMES_MATCH)
  175.         printf("\t%s\n", next->path);
  176.     else {
  177.         printf("\t"); print_fpath(next->path, next->dta.ff_name);
  178.         printf("\n");
  179.     }
  180.  
  181.     next->printed = 1;
  182. }
  183.  
  184.  
  185.  
  186. /*
  187.  * print_id_menu
  188.  *
  189.  * given a starting point in the file list, print out an interactive delete
  190.  * menu.
  191.  */
  192. void print_id_menu(FILE_LIST **menu, int num_items)
  193.  
  194. {
  195.     int i;
  196.  
  197.     print_match_header(menu[0]);
  198.     for (i = 0; i < num_items; i++)
  199.         print_next_match(menu[i], i+1);
  200. }
  201.  
  202.  
  203.  
  204. /*
  205.  * cmpflist
  206.  *
  207.  * returns non-zero if the FILE_LIST parameter is less/greater than the given
  208.  * dta/path combination according to the sort criteria.  If sort
  209.  * order is ASCENDING,  non-zero returned if FILE_LIST less than dta/path
  210.  * combo, vice-versa for DESCENDING order.
  211.  */
  212. int cmpflist(FILE_LIST *fd, char *path, struct ffblk *dta)
  213.  
  214. {
  215.     long cmptime_tmp;
  216.     int tmp;
  217.  
  218.     switch (Sort_criteria) {
  219.     case NAME_SORT:
  220.         return (Sort_order == ASCENDING)
  221.                     ? (((tmp = strcmp(fd->dta.ff_name, dta->ff_name)) < 0) ||
  222.                        ((tmp == 0) && (strcmp(fd->path, path) <= 0)))
  223.                     : (((tmp = strcmp(fd->dta.ff_name, dta->ff_name)) > 0) ||
  224.                        ((tmp == 0) && (strcmp(fd->path, path) >= 0)));
  225.     case SIZE_SORT:
  226.         return (Sort_order == ASCENDING)
  227.                     ? ((fd->dta.ff_fsize < dta->ff_fsize) ||
  228.                        ((fd->dta.ff_fsize == dta->ff_fsize) &&
  229.                         (strcmp(fd->dta.ff_name, dta->ff_name) < 0)) ||
  230.                        ((fd->dta.ff_fsize == dta->ff_fsize) &&
  231.                         (strcmp(fd->path, path) <= 0)))
  232.                     : ((fd->dta.ff_fsize > dta->ff_fsize) ||
  233.                        ((fd->dta.ff_fsize == dta->ff_fsize) &&
  234.                         (strcmp(fd->dta.ff_name, dta->ff_name) > 0)) ||
  235.                        ((fd->dta.ff_fsize == dta->ff_fsize) &&
  236.                         (strcmp(fd->path, path) >= 0)));
  237.     case TIME_SORT:
  238.         return (Sort_order == ASCENDING)
  239.                     ? (((cmptime_tmp = cmptime(&fd->dta, dta)) < 0) ||
  240.                        ((cmptime_tmp == 0) &&
  241.                         ((tmp = strcmp(fd->dta.ff_name,
  242.                                        dta->ff_name)) < 0)) ||
  243.                         ((tmp == 0) && (strcmp(fd->path, path) <= 0)))
  244.                     : (((cmptime_tmp = cmptime(&fd->dta, dta)) > 0) ||
  245.                        ((cmptime_tmp == 0) &&
  246.                         ((tmp = strcmp(fd->dta.ff_name,
  247.                                        dta->ff_name)) > 0)) ||
  248.                         ((tmp == 0) && (strcmp(fd->path, path) >= 0)));
  249.     default:
  250.         return 0;    /* unknown sort criteria */
  251.     }
  252. }
  253.  
  254.  
  255.  
  256. /*
  257.  * cmpflist_eq
  258.  *
  259.  * returns non-zero if the two FILE_LIST parameters are equal according to the
  260.  * sort criteria.
  261.  */
  262. int cmpflist_eq(FILE_LIST *fd1, FILE_LIST *fd2)
  263.  
  264. {
  265.     if (fd1 == NULL)
  266.         return (fd2 == NULL);
  267.     else if (fd2 == NULL)
  268.         return 0;
  269.     switch (Sort_criteria) {
  270.     case NAME_SORT:
  271.         return !strcmp(fd1->dta.ff_name, fd2->dta.ff_name);
  272.     case SIZE_SORT:
  273.         return (fd1->dta.ff_fsize == fd2->dta.ff_fsize);
  274.     case TIME_SORT:
  275.         return !cmptime(&fd1->dta, &fd2->dta);
  276.     default:
  277.         return 0;    /* unknown sort criteria */
  278.     }
  279. }
  280.  
  281.  
  282.  
  283. /*
  284.  * files_match
  285.  *
  286.  * return non-zero if the given two files 'match' according to names and the
  287.  * criteria set by the flags (contents, date/time, size or almost any
  288.  * combination of these).
  289.  */
  290. int files_match(FILE_LIST *file1, FILE_LIST *file2)
  291.  
  292. {
  293.     return (((!(Match_criteria & NAMES_MATCH)) ||
  294.              (!strcmp(file1->dta.ff_name, file2->dta.ff_name))) &&
  295.             ((!(Match_criteria & SIZES_MATCH)) ||
  296.              (file1->dta.ff_fsize == file2->dta.ff_fsize)) &&
  297.             ((!(Match_criteria & TIMES_MATCH)) ||
  298.              (!cmptime(&file1->dta, &file2->dta))) &&
  299.             ((!(Match_criteria & CONTENTS_MATCH)) ||
  300.              (compare_path_name_files(file1->path, file1->dta.ff_name,
  301.                                        file2->path, file2->dta.ff_name))));
  302. }
  303.  
  304.  
  305.  
  306. /*
  307.  * gen_list
  308.  *
  309.  * given a path, generate a list of all files in the path and its
  310.  * subdirectories.
  311.  */
  312. void gen_list(char *path)
  313.  
  314. {
  315.     struct ffblk dta;
  316.     char *path_list, *save_path;
  317.  
  318.     if (path == NULL)
  319.         return;
  320.     path_list = append_dir_to_path(path, ADD_TO_PATH);
  321.     if ((findfirst(path_list, &dta, FA_DIREC) >= 0) &&
  322.         ((save_path = malloc((size_t) (strlen(path)+1))) != NULL)) {
  323.         strcpy(save_path, path);
  324.         do {
  325.             if (dta.ff_attrib & FA_DIREC)
  326.                 gen_list_of_dir(path, dta.ff_name);
  327.             else
  328.                 add_file_to_list(save_path, &dta);
  329.         } while (!findnext(&dta));
  330.     }
  331.  
  332.     free(path_list);
  333. }
  334.  
  335.  
  336.  
  337. /*
  338.  * add_file_to_list
  339.  *
  340.  * given a path and a file on the path, add it to the list according to the
  341.  * sort criteria.
  342.  */
  343. void add_file_to_list(char *path, struct ffblk *dta)
  344.  
  345. {
  346.     FILE_LIST *prev = NULL, *new, *cur = F_list;
  347.  
  348.     if (Sorted)
  349.         while ((cur != NULL) && (cmpflist(cur, path, dta))) {
  350.             prev = cur;
  351.             cur = cur->next;
  352.         }
  353.  
  354.     if ((new = malloc((size_t) sizeof(FILE_LIST))) == NULL) {
  355.         printf("add_file_to_list: memory allocation failure\n");
  356.         exit(-1);
  357.     }
  358.     else {
  359.         memcpy(&new->dta, dta, sizeof(struct ffblk));
  360.         new->path = path;
  361.         new->added = 0;
  362.         new->printed = 0;
  363.         new->next = cur;
  364.         if (prev == NULL)
  365.             F_list = new;
  366.         else
  367.             prev->next = new;
  368.     }
  369. }
  370.  
  371.  
  372.  
  373. /*
  374.  * gen_list_of_dir
  375.  *
  376.  * given a path and a sub-directory, call 'gen_list()' to generate a list
  377.  * of the sub-directory on the path.
  378.  */
  379. void gen_list_of_dir(char *path, char *subdir)
  380.  
  381. {
  382.     char *new_path;
  383.  
  384.     if (!is_special(subdir)) {
  385.         gen_list(new_path = append_dir_to_path(path, subdir));
  386.         if (v_flag > 1) {
  387.             printf("Searching    ");
  388.             print_fpath(path, subdir);
  389.             printf("\n");
  390.         }
  391.         free(new_path);
  392.     }
  393. }
  394.  
  395.  
  396.  
  397. /*
  398.  * list_files
  399.  *
  400.  * given a path, generate a linked list of files on the path or (recursively)
  401.  * its subdirectories.  If 'sorted' is non-zero, make sure the list is
  402.  * sorted.
  403.  */
  404. void list_files(char *prog_name, char *path, char sorted)
  405.  
  406. {
  407.     struct stat statbuf;
  408.     static char target_dir[MAX_STR];
  409.  
  410.     if (just_disk(path)){
  411.         get_cur_path(path, target_dir);
  412.         path = target_dir;
  413.     }
  414.  
  415.     if  ((access(path, 0)) || ((!stat(path, &statbuf)) &&
  416.           (!(statbuf.st_mode & S_IFDIR)))) {
  417.         printf("%s: directory %s does not exist\n", prog_name, path);
  418.         print_help();
  419.         exit(-1);
  420.     }
  421.     else {
  422.         Sorted = sorted;
  423.         gen_list(path);
  424.         if (v_flag > 1)
  425.             printf("\n");
  426.     }
  427. }
  428.  
  429. void get_cur_path(char *new, char *target_dir)
  430. {
  431.     char cur_dir[MAX_STR];
  432.  
  433.     getcwd(cur_dir, MAX_STR);
  434.     change_disk(new, cur_dir);
  435.     getcwd(target_dir, MAX_STR);
  436.     setdisk(*cur_dir - 'A');
  437.     chdir(cur_dir);
  438. }
  439.  
  440.  
  441. void change_disk(char *dir, char *cur_dir)
  442. {
  443.     int maxdrives;
  444.  
  445.     if (isupper(*dir))
  446.         tolower(*dir);
  447.     maxdrives = setdisk(*dir - 'a');
  448.     if (maxdrives < (*dir - 'a') + 1){
  449.         setdisk(*cur_dir - 'A');
  450.         printf("drive '%c' is not accessable\n", *dir);
  451.         print_help();
  452.         exit(-1);
  453.     }
  454.  
  455. }
  456.  
  457. /*
  458.  *    just_disk()
  459.  *
  460.  *    Input:
  461.  *        dir - the directory to be checked
  462.  *    Output:
  463.  *        returns : 
  464.  *            1 - if 'dir' is a current directory (ie 'X:')
  465.  *            0 - otherwise
  466.  */
  467.  
  468. int just_disk(char *dir)
  469. {
  470.     if ((strlen(dir) == 2) && (*(dir + 1) == ':'))
  471.             return(1);
  472.     else
  473.         return(0);
  474. }
  475.  
  476.  
  477. /*
  478.  * print_flist
  479.  *
  480.  * given a pointer to the first entry of a file list, dump the list to standard
  481.  * output
  482.  */
  483. void print_flist(FILE_LIST *flist)
  484.  
  485. {
  486.     for (;flist != NULL; flist = flist->next)
  487.         printf("path = %s\tname = %s\n", flist->path, flist->dta.ff_name);
  488. }
  489.  
  490.  
  491.  
  492. /*
  493.  * compare_path_name_files
  494.  *
  495.  * given a pair of files specified by path and name, return non-zero if their
  496.  * contents match, zero if contents don't match.
  497.  */
  498. int compare_path_name_files(char *path1, char *name1, char *path2, char *name2)
  499.  
  500. {
  501.     int ret_val;
  502.     char *file1;
  503.     char *file2;
  504.  
  505.     file1 = append_dir_to_path(path1, name1);
  506.     file2 = append_dir_to_path(path2, name2);
  507.     if ((file1 == NULL) || (file2 == NULL)) {
  508.         printf("compare_path_name_files: memory allocation failed!\n");
  509.         exit(-1);
  510.     }
  511.  
  512.     ret_val = compare_files(file1, file2);
  513.  
  514.     free(file1);
  515.     free(file2);
  516.  
  517.     return ret_val;
  518. }
  519.  
  520.  
  521.  
  522. /*
  523.  * delete_path_name_file
  524.  *
  525.  * given a file specified by path and name, return zero if the file was
  526.  * successfully deleted, non-zero if not.  'force' parameter, if non-zero, will
  527.  * try to change the mode of a file from read-only to delete it.
  528.  */
  529. int delete_path_name_file(char *path, char *f_name, char force)
  530.  
  531. {
  532.     char *file = append_dir_to_path(path, f_name);
  533.     int ret_val;
  534.  
  535.     if (file == NULL) {
  536.         printf("delete_path_name_file: memory allocation failed\n");
  537.         exit(-1);
  538.     }
  539.  
  540.     ret_val = delete_file(file, force);
  541.  
  542.     free(file);
  543.  
  544.     return ret_val;
  545. }
  546.